package grpc

import (
	"context"
	"fmt"
	"github.com/goAdminMicroService/internal/pkg/consul"
	_ "github.com/mbobakov/grpc-consul-resolver" // It's important
	"github.com/pkg/errors"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"time"
)

type ClientOptions struct {
	Wait            time.Duration     // 等待时间
	Tag             string            // 标签
	GrpcDialOptions []grpc.DialOption // 拨号
}

// 创建客户端选项
func NewClientOptions(v *viper.Viper) (*ClientOptions, error) {
	var (
		err error
		o   = new(ClientOptions)
	)
	if err = v.UnmarshalKey("grpc.client", o); err != nil {
		return nil, err
	}
	// 使用非安全模式连接
	o.GrpcDialOptions = append(o.GrpcDialOptions, grpc.WithInsecure())
	return o, nil
}

type ClientOptional func(o *ClientOptions)

type Client struct {
	consulOptions *consul.Options
	o             *ClientOptions
}

// 实例化 client
func NewClient(consulOptions *consul.Options, o *ClientOptions) (*Client, error) {
	return &Client{
		consulOptions: consulOptions,
		o:             o,
	}, nil
}

// 拨号
func (c *Client) Dial(service string, options ...ClientOptional) (*grpc.ClientConn, error) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	o := &ClientOptions{
		Wait:            time.Second * 5,
		Tag:             c.o.Tag,
		GrpcDialOptions: c.o.GrpcDialOptions,
	}

	for _, option := range options {
		option(o)
	}
	target := fmt.Sprintf("consul://%s/%s?wait=%s&tag=%s", c.consulOptions.Addr, service, o.Wait, o.Tag)
	// 拨号
	conn, err := grpc.DialContext(ctx, target, o.GrpcDialOptions...)
	if err != nil {
		return nil, errors.Wrap(err, "grpc dial error")
	}
	return conn, nil
}
